package com.hengpeng.itfin.domain.draw.common;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.Calendar;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

/**
 * @author shanguogang
 * @version 1.0
 */
public class FileZipHelper
{
	private static Log logger = LogFactory.getLog(FileZipHelper.class);

	/**
	 * 压缩一层目录下的所有文件或压缩单个文件
	 * @param filePath 要压缩的文件路径 （单个文件需含文件名）
	 * @param toFilePath 压缩后的文件路径 含文件名
	 * @param isDelete 是否删除原路径 true为删除 false为不删除
	 */
	public static void zip(String filePath, String toFilePath, boolean isDelete)
	{
		File file = new File(filePath);
		if (file.isDirectory())
		{// 是否为文件目录，是为true
			zipFiles(filePath, toFilePath);
			if (isDelete)
			{
				String[] files = file.list();
				for (int i = 0; i < files.length; i++)
				{
					File f = new File(filePath + "\\" + files[i]);
					f.delete();
				}
				file.delete();
			}
		}
		else
		{
			zipFile(filePath, toFilePath);
			if (isDelete)
			{
				file.delete();
			}
		}

	}

	/**
	 * 压缩某路径的单个文件
	 * @param filePath 要压缩的文件的路径（含文件名 如：d:\\tt.txt）
	 * @param zipname 压缩后的路径（含压缩后文件名 如：d:\\tt.zip）
	 */
	public static boolean zipFile(String filePath, String zipname)
	{
		logger.info("generating zip file ...");
		boolean success = true;
		FileOutputStream fos = null;
		ZipOutputStream zipOut = null;
		FileInputStream fis = null;
		try
		{
			fos = new FileOutputStream(zipname);// 创建文件输出流（低级流）
			zipOut = new ZipOutputStream(fos);// 创建zip文件输出流

			File f = new File(filePath);
			fis = new FileInputStream(filePath);
			ZipEntry ze = new ZipEntry(f.getName());
			zipOut.putNextEntry(ze);
			int c = 0;
			while ((c = fis.read()) != -1)
			{
				zipOut.write(c);
			}
			logger.info("zip file is generated successfully.");
		}
		catch (FileNotFoundException ex)
		{
			ex.printStackTrace();
			logger.error(ex);
			success = false;
		}
		catch (IOException ex)
		{
			ex.printStackTrace();
			logger.error(ex);
			success = false;
		}
		finally
		{
			try
			{
				if (fis != null)
					fis.close();
				if (zipOut != null)
					zipOut.close();
			}
			catch (IOException ex)
			{
				ex.printStackTrace();
				logger.error(ex);
			}
		}
		return success;
	}

	/**
	 * 压缩某路径下所有文件
	 * @param filePath 要压缩的路径
	 * @param zipname 压缩后的路径（含压缩后文件名 如：d:\\tt.zip）
	 */
	private static void zipFiles(String filePath, String zipname)
	{
		FileOutputStream fos = null;
		ZipOutputStream zipOut = null;
		String[] files = (new File(filePath)).list();
		try
		{
			fos = new FileOutputStream(zipname);// 创建文件输出流（低级流）
			zipOut = new ZipOutputStream(fos);// 创建zip文件输出流
			int i = 0;

			for (i = 0; i < files.length; i++)
			{
				File f = new File(files[i]);
				FileInputStream fis = new FileInputStream(filePath + "\\" + files[i]);
				ZipEntry ze = new ZipEntry(f.getName());
				zipOut.putNextEntry(ze);
				int c = 0;
				while ((c = fis.read()) != -1)
				{
					zipOut.write(c);
				}
				fis.close();

			}
			zipOut.close();
		}
		catch (FileNotFoundException ex)
		{
			ex.printStackTrace();
		}
		catch (IOException ex)
		{
			ex.printStackTrace();
		}
	}

	public static void unzipFile(String unzipfile, String destDir)
	{
		try
		{
			File olddirec = new File(unzipfile); // 解压缩的文件路径(为了获取路径)
			ZipInputStream zin = new ZipInputStream(new FileInputStream(unzipfile));
			ZipEntry entry;
			// 创建文件夹
			while ((entry = zin.getNextEntry()) != null)
			{
				if (entry.isDirectory())
				{
					File directory = new File(olddirec.getParent(), entry.getName());
					if (!directory.exists())
						if (!directory.mkdirs())
							System.exit(0);
					zin.closeEntry();
				}
				if (!entry.isDirectory())
				{
					// File myFile = new File(entry.getName());
					// FileOutputStream fout = new
					// FileOutputStream("d:\\test\\"+myFile.getPath());
					FileOutputStream fout = new FileOutputStream(destDir);
					DataOutputStream dout = new DataOutputStream(fout);
					byte[] b = new byte[1024];
					int len = 0;
					while ((len = zin.read(b)) != -1)
					{
						dout.write(b, 0, len);
					}
					dout.close();
					fout.close();
					zin.closeEntry();
				}
			}
		}
		catch (IOException e)
		{
			e.printStackTrace();
		}
	}

	/**
	 * 读取多个zip文件,并解析对应的zip文件
	 * @param zipfiles tt.zip, ttt.zip
	 * @param filepath 如：d:\\
	 */
	public static Map<String, byte[]> unZip(List<String> zipList, String path, String charset) throws IOException
	{
		if (zipList == null)
			return new HashMap<String, byte[]>();
		Map<String, byte[]> result = new HashMap<String, byte[]>();
		// byte[] buf;
		String filePath = path;
		if (filePath != null)
		{
			if (!filePath.endsWith("/"))
				filePath += "/";
		}
		else
		{
			filePath = "";
		}
		for (String zipfile : zipList)
		{
			result.putAll(unZip(filePath + zipfile, charset));
		}

		return result;
	}

	/**
	 * 读取多个zip文件,并解析对应的zip文件
	 * @param zipfiles tt.zip, ttt.zip
	 * @param filepath 如：d:\\
	 */
	public static Map<String, byte[]> unZip(String zipfiles[], String path, String charset) throws IOException
	{
		if (zipfiles == null)
			return new HashMap<String, byte[]>();
		Map<String, byte[]> result = new HashMap<String, byte[]>();
		// byte[] buf;
		String filePath = path;
		if (filePath != null)
		{
			if (!filePath.endsWith("/"))
				filePath += "/";
		}
		else
		{
			filePath = "";
		}
		for (int i = 0; i < zipfiles.length; i++)
		{
			result.putAll(unZip(filePath + zipfiles[i], charset));
		}

		return result;
	}

	/**
	 * 读取单个zip文件,并解析这个zip文件,解析支付宝提现下载文件专用.
	 * @param filepath 如：d:\\tt.zip
	 */
	public static Map<String, byte[]> unZip(String filepath, String charset)
	{
		Map<String, byte[]> result = new HashMap<String, byte[]>();
		BufferedReader br = null;
		ZipFile zf = null;
		try
		{
			zf = new ZipFile(filepath);
			Enumeration<?> entries = zf.entries();
			while (entries.hasMoreElements())
			{
				ZipEntry ze = (ZipEntry) entries.nextElement();
				long size = ze.getSize();
				logger.info("Read: " + ze.getName() + ", size=" + size);
				if (ze.getName().indexOf(Constants.POSTFIX_CSV) > 0
						&& ze.getName().indexOf(Constants.ALIPAY__RESULT_CSV) == -1)
				{
					if (size > 0)
					{
						StringBuffer sb = new StringBuffer();

						br = new BufferedReader(new InputStreamReader(zf.getInputStream(ze), charset));
						int c;
						while ((c = br.read()) != -1)
						{
							sb.append(String.valueOf((char) c));
						}
						logger.info("content:\r\n" + sb.toString());
						result.put(ze.getName(), sb.toString().getBytes());

					}
				}
			}

		}
		catch (Exception e)
		{
			e.printStackTrace();
			return null;
		}
		finally
		{

			try
			{
				if (zf != null)
				{
					zf.close();
					zf = null;
				}

				if (br != null)
				{
					br.close();
				}
				br = null;
			}
			catch (IOException e)
			{
				e.printStackTrace();
			}
		}
		return result;
	}

	/**
	 * 通过压缩流生成压缩文件
	 * @param zipStream 支付宝返回的压缩流
	 * @param zipname 压缩后的路径（含压缩后文件名 如：d:\\tt.zip）
	 */
	public static Map<String, byte[]> unZip(InputStream is, String zipname) throws IOException
	{
		logger.info("begin to deal with [alipay download zip file] stream...");
		Map<String, byte[]> result = new HashMap<String, byte[]>();
		byte[] buf;
		ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
		ZipEntry zipEntry = zis.getNextEntry();
		while (zipEntry != null)
		{
			if (zipEntry.isDirectory())
			{
				zipEntry = zis.getNextEntry();
				continue;
			}
			else
			{
				if ((int) zipEntry.getSize() > 0)
				{
					buf = new byte[(int) zipEntry.getSize()];
					zis.read(buf, 0, (int) zipEntry.getSize());
					result.put(zipEntry.getName(), buf);
				}
				zipEntry = zis.getNextEntry();
			}
		}
		// 生成压缩文件
		zipFiles(result, zipname);
		logger.info("deal with [alipay download zip file] successfully.");
		return result;
	}

	/**
	 * 压缩数据流
	 * @param fileMap 要压缩文件map
	 * @param zipname 压缩后的路径（含压缩后文件名 如：d:\\tt.zip）
	 */
	private static boolean zipFiles(Map<String, byte[]> fileMap, String zipname)
	{
		boolean success = true;
		FileOutputStream fos = null;
		ZipOutputStream zipOut = null;
		try
		{
			logger.info("begin to generate alipay download zip file...");
			fos = new FileOutputStream(zipname);// 创建文件输出流（低级流）

			zipOut = new ZipOutputStream(fos);// 创建zip文件输出流
			Set<String> keySet = fileMap.keySet();
			String files[] = new String[keySet.size()];
			keySet.toArray(files);
			for (int i = 0; i < files.length; i++)
			{
				File f = new File(files[i]);
				byte[] b = fileMap.get(files[i]);
				ZipEntry ze = new ZipEntry(f.getName());
				zipOut.putNextEntry(ze);
				zipOut.write(b);
			}
			logger.info("generate alipay download zip file successfully .");
		}
		catch (FileNotFoundException ex)
		{
			success = false;
			logger.error(ex);
			ex.printStackTrace();
		}
		catch (IOException ex)
		{
			success = false;
			logger.error(ex);
			ex.printStackTrace();
		}
		finally
		{
			try
			{
				if (zipOut != null)
					zipOut.close();
			}
			catch (IOException ex)
			{
				logger.error(ex);
			}
		}
		return success;
	}

	public static boolean moveFile(File srcFile, String destPath)
	{
		// Destination directory
		File dir = new File(destPath);
		// Move file to new directory
		boolean success = srcFile.renameTo(new File(dir, srcFile.getName()));
		return success;
	}

	/**
	 * 将文件srcFile移动到destPath路径下
	 * @param srcFile
	 * @param destPath
	 * @return
	 */
	public static boolean moveFile(String srcFile, String destPath)
	{
		// File (or directory) to be moved
		File file = new File(srcFile);
		// Destination directory
		File dir = new File(destPath);
		// Move file to new directory
		String before = file.getName().substring(0, file.getName().lastIndexOf("."));
		String after = file.getName().substring(file.getName().lastIndexOf("."));
		String newFileName = before + "-" + Calendar.getInstance().getTimeInMillis() + after;
		boolean success = file.renameTo(new File(dir, newFileName));
		if (success)
		{
			logger.info("备份文件" + srcFile + "到" + destPath + "成功,备份重命名为:" + newFileName);
		}
		else
		{
			logger.info("备份文件" + srcFile + "到" + destPath + "失败");
		}
		file = null;
		return success;
	}

	public static void main(String args[]) throws Exception
	{
		logger.info(moveFile("e:\\test\\20081126230000.csv", "e:\\test\\back-error"));
		logger.info(moveFile("e:\\test\\20081127230000.csv", "e:\\test\\back-error"));
		// logger.info(unZip("E:\\test\\ALIPAY_PAY_RESULT_20081114162800_20081117100042.zip"));//合法zip文件
		// logger.info(unZip("E:\\test\\d.zip"));//非法zip文件
		if (true)
			return;
		// if(!f.exists()) f.createNewFile();
		final int BUFFER = 2048;
		String fileName = "E:\\test\\myfiles.zip";
		String filePath = "E:\\test\\";
		ZipFile zipFile = new ZipFile(fileName);
		Enumeration<?> emu = zipFile.entries();
		int i = 0;
		while (emu.hasMoreElements())
		{
			ZipEntry entry = (ZipEntry) emu.nextElement();
			System.out.println(entry.getName());
			// 会把目录作为一个file读出一次，所以只建立目录就可以，之下的文件还会被迭代到。
			if (entry.isDirectory())
			{
				new File(filePath + entry.getName()).mkdirs();
				continue;
			}
			BufferedInputStream bis = new BufferedInputStream(zipFile.getInputStream(entry));
			File file = new File(filePath + entry.getName());
			// 加入这个的原因是zipfile读取文件是随机读取的，这就造成可能先读取一个文件
			// 而这个文件所在的目录还没有出现过，所以要建出目录来。
			File parent = file.getParentFile();
			if (parent != null && (!parent.exists()))
			{
				parent.mkdirs();
			}
			FileOutputStream fos = new FileOutputStream(file);
			BufferedOutputStream bos = new BufferedOutputStream(fos, BUFFER);
			int count;
			byte data[] = new byte[BUFFER];
			while ((count = bis.read(data, 0, BUFFER)) != -1)
			{
				bos.write(data, 0, count);
			}
			bos.flush();
			bos.close();
			bis.close();
		}
		zipFile.close();
		// unzipFile("e:\\test.zip", "e:\\download\\d");
		// System.out.println(moveFile("c:\\11.text","e:\\"));
	}
}
